
/* #include "BinTree/BinTree.hpp" */
#include "AVL/AVL.hpp"
#include "mylist.h"
#include <iostream>
#include <locale>
#include <vector>

struct single_list {
    void * data;
    struct single_list * next;
};

typedef struct single_list * single_link;
/**
 * @brief 使用二级指针直接直接更新head
 * 指针虽然复杂，但是相比引用意思更加明确
 * 
 * @param head 
 * @param pnode 
 */
void insert_from_head(single_link *head, single_link pnode) {
    pnode->next = *head;
    *head = pnode;
}

void new_node(single_link *plink, void * data) {
    *plink = new single_list;
    (*plink)->data = data;
    (*plink)->next = nullptr;
}

void delete_single_list(single_link * phead) {
    while(*phead) {
        single_link to_delete = *phead;
        *phead = ((*phead)->next);
        delete to_delete;
    }
}

void show(single_link *plink) {
    while(*plink) {
        std::cout << *(int*)((*plink)->data) << " ";
        plink = &((*plink)->next);
    }
}

class Test {
public:
    static void test() {
        // create a tree
        BinTree<int> tree;
        tree.insertAsRoot(12);
        BinNodePosi(int) lc = tree.insertAsLC(tree.root(), 121);
        BinNodePosi(int) rc = tree.insertAsRC(tree.root(), 111);
        BinNodePosi(int) rc_lc = tree.insertAsLC(rc, 90);
        show_BinNodePosi(tree.root());

        // count
        int n = 0;
        auto counter = [&n](int data) -> int
        {
            return ++n;
        };
        tree.travPost(counter);
        std::cout << "the total nodes are " << n << std::endl;

        mylist<double> list;
        int posi = list.appendToTail(1.0);
        list.appendToTail(2.0);
        list.insertFromHead(3.0);
        list.insertAfterIndex(4.0, posi);

        for (int i = list.first(); i != list.end(); i = list.next(i))
        {
            std::cout << list.getData(i) << " ";
        }
        std::cout << std::endl;

        /**
         * @brief test single_list
         *
         */
        single_link head = nullptr;
        single_link pnode = nullptr;
        new_node(&pnode, new int(2));
        insert_from_head(&head, pnode);
        new_node(&pnode, new int(3));
        insert_from_head(&head, pnode);
        new_node(&pnode, new int(4));
        insert_from_head(&head, pnode);
        new_node(&pnode, new int(4));
        insert_from_head(&head, pnode);
        new_node(&pnode, new int(8));
        insert_from_head(&head, pnode);
        new_node(&pnode, new int(0));
        insert_from_head(&head, pnode);
        show(&head);
        std::cout << std::endl;
        delete_single_list(&head);

        AVL<int> avl;
        avl.insert(1);
        avl.insert(2);
        avl.insert(3);
        avl.insert(4);
        avl.insert(5);
        avl.insert(6);
        avl.insert(7);
        show_BinNodePosi(avl.root());
        std::cout << std::endl;
        avl.remove(4);
        show_BinNodePosi(avl.root());
    }
    
    static void testVector() {
        std::vector<int > a = {0, 1, 2, 3, 4, 5};
        auto showVector = [](const std::vector<int>& vec) {
            for(auto item: vec) {
                std::cout << item << " ";
            }
        };

        showVector(a);
        std::cout << std::endl;

        a.insert(a.end() - 1, 12);

        showVector(a);
        std::cout << std::endl;

        a.erase(a.begin() + 2, a.end() - 1);
        a.shrink_to_fit();
        showVector(a);
        std::cout << std::endl;
    }

};

int main(int, char**) {
    Test::testVector();
    Test::test();
    return 0;
}
